package com.common.allCommon;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.http.entity.mime.content.ByteArrayBody;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;

import com.product.android.utils.ImageUploadProcessParams;

/**
 * 图片上传处理
 * 
 * @author huangszh
 *
 */
public class ImageUploadUtils {
	
	/**
	 * 获取上传图片的ByteArrayBody
	 * 
	 * @param context	上下文
	 * @param file	上传图片
	 * @param params 压缩处理参数
	 * @return	ByteArrayBody	null表示处理错误，或者无可用网络
	 */
	@SuppressLint("DefaultLocale")
	public static ByteArrayBody getImageByteArrayBody(Context context,File file,
			ImageUploadProcessParams params) {
		
		ConnectivityManager connectivityManager = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);//获取系统的连接服务
		NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();//获取网络的连接情况	
		
		if(activeNetInfo == null) {
			return null;
		}
		
		if(null != file && file.getName().toLowerCase().endsWith(".gif")) {
			return convertGIFToByteArray(file);
		} else{
			if(activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI){
				// wifi
				return compressAndRotate(file,params.wifi_width,params.wifi_height,params.compress_quality);
			}else{
				// 非wifi
				return compressAndRotate(file,params.no_wifi_width,params.no_wifi_height,params.compress_quality);
			}
		}
	}
	
	/**
	 * 获取上传图片的ByteArrayBody，使用默认的压缩参数#ImageUploadProcessParams
	 * @param context 上下文
	 * @param file 上传图片
	 * @return ByteArrayBody null表示处理错误，或者无可用网络
	 */
	public static ByteArrayBody getImageByteArrayBody(Context context,File file) {
		
		return getImageByteArrayBody(context, file, new ImageUploadProcessParams());
	}
	
	/**
	 * 压缩旋转图片
	 * @param file	图片
	 * @param width 
	 * @param height
	 * @param quality
	 * @return ByteArrayBody
	 */
	public static ByteArrayBody compressAndRotate(File file,int width,int height,int quality) {
		if (!file.exists()) {
			return null;
		}
		
		CompressFormat cf;
		
		//根据宽高判断是否需要采样和压缩
        Bitmap resizeBitmap = decodeSampledBitmapFromFile(file.getPath(), width, height);
       	cf = CompressFormat.JPEG;
        //Log.i("upload","resizeBitmap width = " + resizeBitmap.getWidth());
		int degree = getDegree(file.getPath());
		// 如果旋转角度 > 0,则需要旋转回正确的方向
		if (degree > 0) {
			resizeBitmap = rotateBitmap(resizeBitmap, degree);
		}
		
		ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
		
		resizeBitmap.compress(cf, quality, bos);
		resizeBitmap.recycle();
		String name =  file.getName();
		if(!isImage(name)){
			name += ".jpg";
		}
		ByteArrayBody body = new ByteArrayBody(bos.toByteArray(),name);
		try {
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return body;
	}
	
	/**
	 * gif转成ByteArrayBody
	 * 
	 * @param file gif图
	 * @return	ByteArrayBody null表示文件不存在或者处理异常
	 */
	public static ByteArrayBody convertGIFToByteArray(File file) {
		if (!file.exists()) {
			return null;
		}

		FileInputStream fis = null;
		ByteArrayOutputStream bos = null;
		try {
			fis = new FileInputStream(file);
			bos = new ByteArrayOutputStream();
	        byte[] buf = new byte[1024];
	        for (int readNum; (readNum = fis.read(buf)) != -1;) {
                bos.write(buf, 0, readNum); //no doubt here is 0
                //Writes len bytes from the specified byte array starting at offset off to this byte array output stream.
            }
	        
	        String name =  file.getName();
			if(!isImage(name)){
				name += ".gif";
			}
			ByteArrayBody body = new ByteArrayBody(bos.toByteArray(),name);
			return body;
		}catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}catch (IOException e) {       	
            e.printStackTrace();
        }
		finally{
			try {
	    		if(null != fis){
	    			fis.close();
	    		}
	    		if(null != bos){
	    			bos.close();
	    		}
			} catch (IOException e) {
				e.printStackTrace();
			}   
		}
		return null;
	}
	
	/**
	 * 将文件转为ByteArrayBody
	 * 
	 * @param file	文件
	 * @return	ByteArrayBody 文件不存在或者处理异常
	 */
	public static ByteArrayBody tansferToByteArray(File file) {
		if (!file.exists()) {
			return null;
		}
		FileInputStream stream = null;
		ByteArrayOutputStream out = null;
		try {
			stream = new FileInputStream(file);
			out = new ByteArrayOutputStream(1000);
			byte[] b = new byte[1000];
			int n;
			while ((n = stream.read(b)) != -1) {
				out.write(b, 0, n);
			}
			return new ByteArrayBody(out.toByteArray(), file.getName());
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
            try {
                stream.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

	}
	
	/**
	 * 判断是否图片
	 * 
	 * @param strFile 文件路径
	 * @return
	 */
	public static boolean isImage(String strFile){
		String[] photoSuffixes = new String[] { ".png", ".jpg", ".gif"}; // 注意英文字母全部用小写
		for (String suffix : photoSuffixes) {
			if (strFile.endsWith(suffix)) {
				return true;
			}
		}		
		return false;
	}
	
	/**
     * Decode and sample down a bitmap from a file to the requested width and height.
     *
     * @param filename The full path of the file to decode
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return A bitmap sampled down from the original with the same aspect ratio and dimensions
     *         that are equal to or greater than the requested width and height
     */
    public static Bitmap decodeSampledBitmapFromFile(String filename,
            int reqWidth, int reqHeight) {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filename, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filename, options);
    }
   
    /**    
    * @n<b>函数名称</b>     :decodeSampledBitmapFromFile
    * @brief    限定最大宽的等比缩小原图，比例超过maxRate的返回null,最大宽度不超过reqMaxWidth
    * @see
    * @since    Ver 1.3.0
    * @param  @param path
    * @param  @param reqWidth
    * @param  @param reqHeight
    * @param  @param maxRate
    * @param  @return
    * @return Bitmap
    * @<b>作者</b>          :  daiyf
    * @<b>创建时间</b>      :  2013-11-29下午3:59:25      
   */
   public static Bitmap decodeSampledBitmapFromFile(String path,
           int reqMaxWidth, double maxRate) {

       // First decode with inJustDecodeBounds=true to check dimensions
       final BitmapFactory.Options options = new BitmapFactory.Options();
       options.inJustDecodeBounds = true;
       BitmapFactory.decodeFile(path, options);
       double rate = 0;
       if(options.outWidth < options.outHeight){
       	rate = options.outHeight/options.outWidth;
       }
       else{
       	rate = options.outWidth/options.outHeight;
       }
       //比例超过限制返回空
       if(rate > maxRate){
       	return null;
       }

       // Calculate inSampleSize
       options.inSampleSize = 1;
       int orgWidth = 0;
       if(options.outHeight > options.outWidth){
       	orgWidth = options.outHeight;
       }else {
       	orgWidth = options.outWidth;
       }
       if(orgWidth > reqMaxWidth){
       	options.inSampleSize = orgWidth/reqMaxWidth;
       	if(orgWidth%reqMaxWidth > 0){
       		options.inSampleSize++;
       	}
       }

//       options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

       // Decode bitmap with inSampleSize set
       options.inJustDecodeBounds = false;
       return BitmapFactory.decodeFile(path, options);
   }
       
    
    /**
     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding
     * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates
     * the closest inSampleSize that will result in the final decoded bitmap having a width and
     * height equal to or larger than the requested width and height. This implementation does not
     * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but
     * results in a larger bitmap which isn't as useful for caching purposes.
     *
     * @param options An options object with out* params already populated (run through a decode*
     *            method with inJustDecodeBounds==true
     * @param reqWidth The requested width of the resulting bitmap
     * @param reqHeight The requested height of the resulting bitmap
     * @return The value to be used for inSampleSize
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        int tagwidth; // 目标宽度
        int orgwidth; // 原始宽度
        int inSampleSize = 1;// 初始采样比为1
        // 取宽高中较小的设置为原始宽度
        if(options.outHeight > options.outWidth){
        	orgwidth = options.outWidth;
        }else {
        	orgwidth = options.outHeight;
        }
        // 取目标宽高 中较小的设置为目标宽度
        if(reqHeight > reqWidth){
        	tagwidth = reqWidth;
        }else {
        	tagwidth = reqHeight;
        }

        // 如果原始宽度 大于 目标宽度则需要压缩
        if (orgwidth > tagwidth) {
            inSampleSize = Math.round((float) orgwidth / (float) tagwidth);

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger
            // inSampleSize).

            final float totalPixels = options.outWidth * options.outHeight;

            // Anything more than 2x the requested pixels we'll sample down
            // further.
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }
    

    /**
     * 旋转bitmap
     * @param bitmap 原始bitmap
     * @param degree 旋转角度, 0则直接返回原Bitmap
     * @return	Bitmap 处理后的bitmap
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, int degree) {
		if (degree == 0)
			return bitmap;
		Matrix matrix = new Matrix();
		matrix.postRotate(degree);
		try {
			Bitmap tempBmp = Bitmap.createBitmap(bitmap, 0, 0,
					bitmap.getWidth(), bitmap.getHeight(), matrix, true);

			// Bitmap操作完应该显示的释放
			bitmap.recycle();
			bitmap = tempBmp;
		} catch (OutOfMemoryError ex) {
			// Android123建议大家如何出现了内存不足异常，最好return 原始的bitmap对象。.
		}
		return bitmap;
	}

	/**
	 * 从exif中获取角度
	 * get degree from exif
	 */
    @TargetApi(Build.VERSION_CODES.ECLAIR)
	public static int getDegree(String filename) {
		int result = 0;
		int orientation = 0;
		try {
			ExifInterface exif = new ExifInterface(filename);
			orientation = exif
					.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);

		} catch (Exception e) {
		}

		switch (orientation) {
		case ExifInterface.ORIENTATION_ROTATE_90:
			result = 90;
			break;
		case ExifInterface.ORIENTATION_ROTATE_180:
			result = 180;
			break;
		case ExifInterface.ORIENTATION_ROTATE_270:
			result = 270;
			break;
		}
		// rotate
		return result;
	}

}
